﻿using System;
using System.Runtime.InteropServices;

namespace MS.Win32
{
    internal static class NativeMethods
    {
        public const int NO_ERROR = 0;
        public const int DEVICE_NOTIFY_SERVICE_HANDLE = 0x00000001;

        public const int PBT_POWERSETTINGCHANGE = 0x8013;
        public const int DBT_DEVICEARRIVAL = 0x8000;
        public const int DBT_DEVICEREMOVECOMPLETE = 0x8004;
        public const int DBT_DEVTYP_DEVICEINTERFACE = 0x00000005;

        public const uint POWERBUTTON_ACTION_INDEX_NOTHING = 0;
        public const uint POWERBUTTON_ACTION_INDEX_SLEEP = 1;
        public const uint POWERBUTTON_ACTION_INDEX_HIBERNATE = 2;
        public const uint POWERBUTTON_ACTION_INDEX_SHUTDOWN = 3;

        public static readonly Guid GUID_DEVINTERFACE_USB_DEVICE = new Guid(0xA5DCBF10, 0x6530, 0x11D2, 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED);
        public static readonly Guid GUID_SYSTEM_BUTTON_SUBGROUP = new Guid(0x4F971E89, 0xEEBD, 0x4455, 0xA8, 0xDE, 0x9E, 0x59, 0x04, 0x0E, 0x73, 0x47);
        public static readonly Guid GUID_LIDCLOSE_ACTION = new Guid(0x5CA83367, 0x6E45, 0x459F, 0xA2, 0x7B, 0x47, 0x6B, 0x1D, 0x01, 0xC9, 0x36);
        public static readonly Guid GUID_LIDSWITCH_STATE_CHANGE = new Guid(0xBA3E0F4D, 0xB817, 0x4094, 0xA2, 0xD1, 0xD5, 0x63, 0x79, 0xE6, 0xA0, 0xF3);

        public const int SERVICE_ACCEPT_STOP = 0x00000001;
        public const int SERVICE_ACCEPT_SHUTDOWN = 0x00000004;
        public const int SERVICE_ACCEPT_HARDWAREPROFILECHANGE = 0x00000020;
        public const int SERVICE_ACCEPT_POWEREVENT = 0x00000040;

        public const int SERVICE_CONTROL_STOP = 0x00000001;
        public const int SERVICE_CONTROL_INTERROGATE = 0x00000004;
        public const int SERVICE_CONTROL_SHUTDOWN = 0x00000005;
        public const int SERVICE_CONTROL_DEVICEEVENT = 0x0000000B;
        public const int SERVICE_CONTROL_POWEREVENT = 0x0000000D;

        [StructLayout(LayoutKind.Sequential)]
        public struct SERVICE_STATUS
        {
            public uint serviceType;
            public uint currentState;
            public uint controlsAccepted;
            public uint win32ExitCode;
            public uint serviceSpecificExitCode;
            public uint checkPoint;
            public uint waitHint;
        }

        public const int SERVICE_WIN32_OWN_PROCESS = 0x00000010;
        public const int SERVICE_WIN32_SHARE_PROCESS = 0x00000020;
        public const int SERVICE_WIN32 = (SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS);

        public const int SERVICE_STOPPED = 0x00000001;
        public const int SERVICE_START_PENDING = 0x00000002;
        public const int SERVICE_STOP_PENDING = 0x00000003;
        public const int SERVICE_RUNNING = 0x00000004;

        [StructLayout(LayoutKind.Sequential)]
        public struct POWERBROADCAST_SETTING
        {
            public Guid PowerSetting;
            public uint DataLength;
            public byte Data;
        }

        public enum POWER_DATA_ACCESSOR
        {
            ACCESS_AC_POWER_SETTING_INDEX = 0,  // 0x0
            ACCESS_DC_POWER_SETTING_INDEX = 1,  // 0x1
            ACCESS_SCHEME = 16, // 0x10
            ACCESS_SUBGROUP = 17, // 0x11
            ACCESS_INDIVIDUAL_SETTING = 18, // 0x12
            ACCESS_ACTIVE_SCHEME = 19, // 0x13
            ACCESS_CREATE_SCHEME = 20 // 0x14
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct DEV_BROADCAST_HDR
        {
            public uint dbch_size;
            public uint dbch_devicetype;
            public uint dbch_reserved;
        }

        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        public struct DEV_BROADCAST_DEVICEINTERFACE
        {
            public uint dbcc_size;
            public uint dbcc_devicetype;
            public uint dbcc_reserved;
            public Guid dbcc_classguid;
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
            public string dbcc_name;
        }

        public delegate void ServiceControlCallback(int control);
        public delegate int ServiceControlCallbackEx(int control, int eventType, IntPtr eventData, IntPtr eventContext);

        [DllImport(ExternDll.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)]
        public static extern IntPtr RegisterServiceCtrlHandler(string serviceName, Delegate callback);

        [DllImport(ExternDll.Advapi32, CharSet = CharSet.Unicode, SetLastError = true)]
        public static extern IntPtr RegisterServiceCtrlHandlerEx(string serviceName, Delegate callback, IntPtr userData);

        [DllImport(ExternDll.Advapi32, SetLastError = true)]
        public unsafe static extern bool SetServiceStatus(IntPtr serviceStatusHandle, SERVICE_STATUS* status);

        [DllImport(ExternDll.Powrprof, SetLastError = true)]
        public static extern uint PowerGetActiveScheme(IntPtr RootPowerKey, ref IntPtr ActivePolicyGuid);

        [DllImport(ExternDll.Powrprof, SetLastError = true)]
        public static extern uint PowerSetActiveScheme(IntPtr RootPowerKey, ref Guid ActivePolicyGuid);

        [DllImport(ExternDll.Powrprof, SetLastError = true)]
        public static extern uint PowerReadACValueIndex(IntPtr RootPowerKey, ref Guid SchemeGuid, ref Guid SubGroupOfPowerSettingsGuid, ref Guid PowerSettingGuid, ref uint AcValueIndex);

        [DllImport(ExternDll.Powrprof, SetLastError = true)]
        public static extern uint PowerWriteACValueIndex(IntPtr RootPowerKey, ref Guid SchemeGuid, ref Guid SubGroupOfPowerSettingsGuid, ref Guid PowerSettingGuid, uint AcValueIndex);

        [DllImport(ExternDll.Powrprof, SetLastError = true)]
        public static extern uint PowerReadDCValueIndex(IntPtr RootPowerKey, ref Guid SchemeGuid, ref Guid SubGroupOfPowerSettingsGuid, ref Guid PowerSettingGuid, ref uint DcValueIndex);

        [DllImport(ExternDll.Powrprof, SetLastError = true)]
        public static extern uint PowerWriteDCValueIndex(IntPtr RootPowerKey, ref Guid SchemeGuid, ref Guid SubGroupOfPowerSettingsGuid, ref Guid PowerSettingGuid, uint DcValueIndex);
    }
}
